import axios from 'axios'
// 导入 element-ui 的 message 的提示信息
import { Message } from 'element-ui'
import store from '@/store'
import { getTimeStamp } from './auth'
import router from '@/router'
// 定义超时时间
const TimeOut = 3600
const service = axios.create({
   // 这个值随执行命令发生变化
   // 开发环境 npm run dev --> /dev-api
   // 生产环境 npm run build --> /prod-api
   // 因为我们反向代理是 /api ， 所以我们需要把开发环境的地址改为 /api
   // 读取环境变量 process.env，必须是 VUE_APP 开头的

   // 在 npm run dev 的时候这个地址就替换了
   // 编译阶段：complie ：npm run dev/build/serve 读取并运行，node阶段：环境变量，vue.config 等
   // 运行命令的阶段，把代码变成浏览器认识的东西，把整个代码变了一次，vue 的脚手架带的内容
   // 运行阶段：runtime

   baseURL: process.env.VUE_APP_BASE_API,
   // 超时时间
   timeout: 5000
})
// 请求拦截器
// config 成功时执行
service.interceptors.request.use(
   config => {
      // config 是请求的配置信息
      // 如果token存在 注入 token
      if (store.getters.token) {
         // 只有在有 token 的情况下才有必要去检查时间戳是否超时
         if (IsCheckTimeOut()) {
            // 如果它为 true 就代表过期了
            // token 没用了 因为超时了
            // 登出操作
            store.dispatch('user/logout')
            // 先删除的token 再跳转页面
            // 跳到登录页
            router.push('/login')
            return Promise.reject(new Error('token超时了'))
         }
         // config.headers 对象中添加一个 请求头的属性
         config.headers[
            'Authorization'
         ] = `Bearer ${store.getters.token}`
      }
      // 必须要返回
      return config
   },
   error => {
      return Promise.reject(error)
   }
)
// 响应拦截器
service.interceptors.response.use(
   response => {
      // response 就是响应给我们的数据
      // axios 默认加了一层data，所以data里包含的就是所有返回的数据
      const { success, message, data } = response.data
      // 要根据 success 的成功与否决定下边的操作
      // 后台 success 的判断
      if (success) {
         // 如果成功，直接返回数据
         return data
      } else {
         // 提示错误消息
         // 业务已经错了，不能进then，应该进 catch
         Message.error(message)
         // 并没有发现错误对象，人为的实例化一个错误对象
         return Promise.reject(new Error(message))
      }
   },
   // 直接错误，http 返回的错误：例：400  401 之类的
   error => {
      // 被动处理 token 失效
      // 服务器返回的 token 超时信息 ，只有错误了，在返回的数据 code 中
      // error 信息里面有 response 对象 
      // 如果 后台返回错误信息对象，并且返回里带有data对象数据，
      // 并且返回的数据中带有 token 失效的信息
      // 如果只写最后一个，万一返回的数据 data 是一个 undefined 那么页面将会卡住
      // 为什么判断这么多？因为错误信息都在这，有很多种，比如 4 开头啊，5开头啊之类的
      // 但是不一定每个错误信息都给我同时返回数据
      // 虽然出错了，但是后台还是给我返回数据了
      // 如果 error 里边有 response 的对象，说明后台给我们返回数据了
      // 再看 response 的对象 中有没有data的数据，也不一定有
      if (
         error.response &&
         error.response.data &&
         error.response.data.code === 10002
      ) {
         // 当等于 10002 的时候，表示后端告诉我 token 超时
         // 先删除token，再退出登录
         store.dispatch('user/logout')
         router.push('/login')
      } else {
         // 提示错误信息
         Message.error(error.message)
      }
      // 返回执行错误，让当前的执行链跳出成功，直接进入catch
      return Promise.reject(error)
      // login().then().catch()
   }
)
// 是否超时
// 超时逻辑：当前时间 - 缓存中的时间  是否大于时间差
function IsCheckTimeOut() {
   // 当前时间戳
   var currentTime = Date.now()
   // 缓存时间戳
   var timeStamp = getTimeStamp()
   // 注意转换为秒    大于的话 就超时了
   return (currentTime - timeStamp) / 1000 > TimeOut
}
export default service
